// vendor.scss v1.0 | @ajlkn | MIT licensed */

// Vars.

/// Vendor prefixes.
/// @var {list}
$vendor-prefixes: (
        '-moz-',
        '-webkit-',
        '-ms-',
        ''
);

/// Properties that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list}
$vendor-properties: (
  // Animation.
        'animation',
        'animation-delay',
        'animation-direction',
        'animation-duration',
        'animation-fill-mode',
        'animation-iteration-count',
        'animation-name',
        'animation-play-state',
        'animation-timing-function',
          // Appearance.
        'appearance',
          // Backdrop filter.
        'backdrop-filter',
          // Background image options.
        'background-clip',
        'background-origin',
        'background-size',
          // Box sizing.
        'box-sizing',
          // Clip path.
        'clip-path',
          // Filter effects.
        'filter',
          // Flexbox.
        'align-content',
        'align-items',
        'align-self',
        'flex',
        'flex-basis',
        'flex-direction',
        'flex-flow',
        'flex-grow',
        'flex-shrink',
        'flex-wrap',
        'justify-content',
        'order',
          // Font feature.
        'font-feature-settings',
        'font-language-override',
        'font-variant-ligatures',
          // Font kerning.
        'font-kerning',
          // Fragmented borders and backgrounds.
        'box-decoration-break',
          // Grid layout.
        'grid-column',
        'grid-column-align',
        'grid-column-end',
        'grid-column-start',
        'grid-row',
        'grid-row-align',
        'grid-row-end',
        'grid-row-start',
        'grid-template-columns',
        'grid-template-rows',
          // Hyphens.
        'hyphens',
        'word-break',
          // Masks.
        'mask',
        'mask-border',
        'mask-border-outset',
        'mask-border-repeat',
        'mask-border-slice',
        'mask-border-source',
        'mask-border-width',
        'mask-clip',
        'mask-composite',
        'mask-image',
        'mask-origin',
        'mask-position',
        'mask-repeat',
        'mask-size',
          // Multicolumn.
        'break-after',
        'break-before',
        'break-inside',
        'column-count',
        'column-fill',
        'column-gap',
        'column-rule',
        'column-rule-color',
        'column-rule-style',
        'column-rule-width',
        'column-span',
        'column-width',
        'columns',
          // Object fit.
        'object-fit',
        'object-position',
          // Regions.
        'flow-from',
        'flow-into',
        'region-fragment',
          // Scroll snap points.
        'scroll-snap-coordinate',
        'scroll-snap-destination',
        'scroll-snap-points-x',
        'scroll-snap-points-y',
        'scroll-snap-type',
          // Shapes.
        'shape-image-threshold',
        'shape-margin',
        'shape-outside',
          // Tab size.
        'tab-size',
          // Text align last.
        'text-align-last',
          // Text decoration.
        'text-decoration-color',
        'text-decoration-line',
        'text-decoration-skip',
        'text-decoration-style',
          // Text emphasis.
        'text-emphasis',
        'text-emphasis-color',
        'text-emphasis-position',
        'text-emphasis-style',
          // Text size adjust.
        'text-size-adjust',
          // Text spacing.
        'text-spacing',
          // Transform.
        'transform',
        'transform-origin',
          // Transform 3D.
        'backface-visibility',
        'perspective',
        'perspective-origin',
        'transform-style',
          // Transition.
        'transition',
        'transition-delay',
        'transition-duration',
        'transition-property',
        'transition-timing-function',
          // Unicode bidi.
        'unicode-bidi',
          // User select.
        'user-select',
          // Writing mode.
        'writing-mode',
);

/// Values that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list}
$vendor-values: (
  // Cross fade.
        'cross-fade',
          // Element function.
        'element',
          // Filter function.
        'filter',
          // Flexbox.
        'flex',
        'inline-flex',
          // Grab cursors.
        'grab',
        'grabbing',
          // Gradients.
        'linear-gradient',
        'repeating-linear-gradient',
        'radial-gradient',
        'repeating-radial-gradient',
          // Grid layout.
        'grid',
        'inline-grid',
          // Image set.
        'image-set',
          // Intrinsic width.
        'max-content',
        'min-content',
        'fit-content',
        'fill',
        'fill-available',
        'stretch',
          // Sticky position.
        'sticky',
          // Transform.
        'transform',
          // Zoom cursors.
        'zoom-in',
        'zoom-out',
);

// Functions.

/// Removes a specific item from a list.
/// @author Hugo Giraudel
/// @param {list} $list List.
/// @param {integer} $index Index.
/// @return {list} Updated list.
@function remove-nth($list, $index) {

  $result: null;

  @if type-of($index) != number {
    @warn "$index: #{quote($index)} is not a number for `remove-nth`.";
  } @else if $index == 0 {
    @warn "List index 0 must be a non-zero integer for `remove-nth`.";
  } @else if abs($index) > length($list) {
    @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`.";
  } @else {

    $result: ();
    $index: if($index < 0, length($list) + $index + 1, $index);

    @for $i from 1 through length($list) {

      @if $i != $index {
        $result: append($result, nth($list, $i));
      }

    }

  }

  @return $result;

}

/// Replaces a substring within another string.
/// @author Hugo Giraudel
/// @param {string} $string String.
/// @param {string} $search Substring.
/// @param {string} $replace Replacement.
/// @return {string} Updated string.
@function str-replace($string, $search, $replace: '') {

  $index: str-index($string, $search);

  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
  }

  @return $string;

}

/// Replaces a substring within each string in a list.
/// @param {list} $strings List of strings.
/// @param {string} $search Substring.
/// @param {string} $replace Replacement.
/// @return {list} Updated list of strings.
@function str-replace-all($strings, $search, $replace: '') {

  @each $string in $strings {
    $strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace));
  }

  @return $strings;

}

// Mixins.

/// Wraps @content in vendorized keyframe blocks.
/// @param {string} $name Name.
@mixin keyframes($name) {

  @-moz-keyframes #{$name} {
    @content;
  }
  @-webkit-keyframes #{$name} {
    @content;
  }
  @-ms-keyframes #{$name} {
    @content;
  }
  @keyframes #{$name} {
    @content;
  }

}

/// Vendorizes a declaration's property and/or value(s).
/// @param {string} $property Property.
/// @param {mixed} $value String/list of value(s).
@mixin vendor($property, $value) {

  // Determine if property should expand.
  $expandProperty: index($vendor-properties, $property);

  // Determine if value should expand (and if so, add '-prefix-' placeholder).
  $expandValue: false;

  @each $x in $value {
    @each $y in $vendor-values {
      @if $y == str-slice($x, 1, str-length($y)) {

        $value: set-nth($value, index($value, $x), '-prefix-' + $x);
        $expandValue: true;

      }
    }
  }

  // Expand property?
  @if $expandProperty {
    @each $vendor in $vendor-prefixes {
      #{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
    }
  }

    // Expand just the value?
  @else if $expandValue {
    @each $vendor in $vendor-prefixes {
      #{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
    }
  }

    // Neither? Treat them as a normal declaration.
  @else {
    #{$property}: #{$value};
  }

}